﻿
namespace ZDS

open System
open System.Collections
open System.Collections.Generic

type ZArrLstIterator<'t>(m_arrlst : ZArrayList<'t>) =
    
    let mutable m_index = -1

    interface IEnumerator<'t> with
        member this.Current =
            m_arrlst.[m_index]

    interface IEnumerator with
        member this.MoveNext() = 
            m_index <- m_index + 1
            m_index < m_arrlst.Size

        member this.Reset() =
            m_index <- -1

        member this.Current = 
            let value = (this :> IEnumerator<'t>).Current
            box value

    interface IDisposable with
        member this.Dispose() =
            ()

and ZArrayList<'t>(m_capacity) = 

    let m_array = Array.zeroCreate<'t>(m_capacity)
    let mutable m_availPos = 0

    member this.Item 
        with get index =
            if index >=0 && index < m_availPos then 
                m_array.[index]
            else
                raise <| ZError(ErrorCode.OutofRange)

        and set index value = 
            if index >= 0 && index < m_availPos then
                m_array.[index] <- value
            else
                raise <| ZError(ErrorCode.OutofRange)

    member this.Size = m_availPos

    member this.Capacity = m_capacity

    member this.Append value =
        if m_availPos >= m_capacity then
            raise <| ZError(ErrorCode.Full)

        m_array.[m_availPos] <- value
        m_availPos <- m_availPos + 1

    member this.Insert pos value =
        if m_availPos >= m_capacity then
            raise <| ZError(ErrorCode.Full)
            
        // allow the value be inserted at the rear
        if pos >= 0 && pos <= m_availPos then
            for i = (m_availPos - 1) downto pos do
                m_array.[i+1] <- m_array.[i]

            m_array.[pos] <- value
            m_availPos <- m_availPos + 1
        else
            raise <| ZError(ErrorCode.OutofRange)

    member this.Remove pos = 
        if m_availPos = 0 then
            raise <| ZError(ErrorCode.Empty)

        if pos >= 0 && pos < m_availPos then
            let toremove = m_array.[pos]

            for i = (pos + 1) to (m_availPos - 1) do
                m_array.[i-1] <- m_array.[i]

            m_availPos <- m_availPos - 1
            toremove
        else
            raise <| ZError(ErrorCode.OutofRange)

    // ######################### interface IEnumerable
    interface IEnumerable<'t> with
        member this.GetEnumerator() =
            new ZArrLstIterator<'t>(this) :> IEnumerator<'t>

    interface IEnumerable with
        member this.GetEnumerator() =
            new ZArrLstIterator<'t>(this) :> IEnumerator

        




        

